package com.example.demo.AliOSS;

import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.GetObjectRequest;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.example.demo.AliOSS.constant.OssConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;

/**
 * 阿里-文件上传
 *
 * @author FF998
 */
@RestController
@RequestMapping("/AliOSS")
@Slf4j
public class UploadFileController {

    @Autowired
    private OssConstant ossConstant;

    @PostMapping(value = "/file/upload", name = "文件上传")
    public JSONObject fileUpload(@RequestPart("file") MultipartFile multipartFile) throws Exception {

        String fileName = multipartFile.getOriginalFilename();
        assert fileName != null;
        File file = new File(fileName);
        JSONObject object = new JSONObject();
        object.put("fileName",fileName);
        OutputStream out = null;
        try {
            //获取文件流，以文件流的方式输出到新文件
            out = new FileOutputStream(file);
            byte[] ss = multipartFile.getBytes();
            for (byte s : ss) {
                out.write(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        // 填写Bucket名称，例如examplebucket。
        String bucketName = ossConstant.getBucketName();
        // 填写Object完整路径，完整路径中不能包含Bucket名称，例如exampledir/exampleobject.txt。
        String objectName = ossConstant.getUploadPath() + fileName;
        // 创建OSSClient实例。
        OSS ossClient = insOssClient();

        try {
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, file);

            // 上传字符串。
            PutObjectResult result = ossClient.putObject(putObjectRequest);

            // 操作完上的文件 需要删除在根目录下生成的文件
            File f = new File(file.toURI());
            if (f.delete()) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败");
            }

        } catch (OSSException oe) {
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            log.info("捕获OSSException，这意味着您的请求已发送到OSS，但由于某种原因被错误响应拒绝。");
        } catch (ClientException ce) {
            System.out.println("Error Message:" + ce.getMessage());
            log.info("捕获了一个ClientException，这意味着客户端在试图与OSS通信时遇到了严重的内部问题，例如无法访问网络。");
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return object;
    }

    @GetMapping(value = "/file/delete", name = "文件删除")
    public String fileDelete(@RequestParam(value = "name") String name) {
        // 填写Bucket名称，例如examplebucket。
        String bucketName = ossConstant.getBucketName();
        // 填写文件完整路径。文件完整路径中不能包含Bucket名称。
        String objectName = ossConstant.getUploadPath() + name;
        // 创建OSSClient实例。
        OSS ossClient = insOssClient();

        try {
            // 删除文件或目录。如果要删除目录，目录必须为空。
            ossClient.deleteObject(bucketName, objectName);
        } catch (OSSException oe) {
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            log.info("捕获OSSException，这意味着您的请求已发送到OSS，但由于某种原因被错误响应拒绝。");
        } catch (ClientException ce) {
            System.out.println("Error Message:" + ce.getMessage());
            log.info("捕获了一个ClientException，这意味着客户端在试图与OSS通信时遇到了严重的内部问题，例如无法访问网络。");
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
                return "Ok";
            }
            return "Error";
        }
    }

    @GetMapping(value = "/file/download", name = "文件下载")
    public String fileDownload(@RequestParam(value = "name") String name) {
        // 填写Bucket名称，例如examplebucket。
        String bucketName = ossConstant.getBucketName();
        // 填写不包含Bucket名称在内的Object完整路径，例如testfolder/exampleobject.txt。
        String objectName = ossConstant.getUploadPath() + name;
        // 文件目的地
        String pathName = "C:\\Users\\FF998\\Desktop\\Work\\" + name;
        // 创建OSSClient实例。
        OSS ossClient = insOssClient();

        try {
            // 下载Object到本地文件，并保存到指定的本地路径中。如果指定的本地文件存在会覆盖，不存在则新建。
            // 如果未指定本地路径，则下载后的文件默认保存到示例程序所属项目对应本地路径中。
            ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName));
        } catch (OSSException oe) {
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
            log.info("捕获OSSException，这意味着您的请求已发送到OSS，但由于某种原因被错误响应拒绝。");
        } catch (ClientException ce) {
            System.out.println("Error Message:" + ce.getMessage());
            log.info("捕获了一个ClientException，这意味着客户端在试图与OSS通信时遇到了严重的内部问题，例如无法访问网络。");
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return "Ok";
    }


    /**
     * 创建OSSClient实例。
     *
     * @return OSS
     */
    public OSS insOssClient(){
        // Endpoint以华东1（杭州）为例，其它Region请按实际情况填写。
        String endpoint = ossConstant.getEndpoint();
        // 阿里云账号AccessKey拥有所有API的访问权限，风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维，请登录RAM控制台创建RAM用户。
        String accessKeyId = ossConstant.getAccessKeyId();
        String accessKeySecret = ossConstant.getAccessKeySecret();
        // 创建OSSClient实例。
        return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
    }
}
